<!--
附件

参数：
maxUploadSize: 最大上传尺寸,单位MB
enablePackDownload: 允许打包下载
storageClass: 存储类型
storageId: 存储ID
recommentUrl: 编辑备注url
uploadUrl: 上传url
deleteUrl: 删除url
rightNameForEdit: 菜单权限
hasEditRight: 数据权限判定回调方法

事件：
// files-uploaded: 上传成功
// files-deleted: 删除成功
-->
<template>
  <div>
    <q-table :columns="columnsInfo" :rows="$d.tableData" :hide-pagination="true" v-model:pagination="$d.paginationInfo"
      v-model:selected="$d.selectedItems" dense hide-selected-banner :no-data-label="$t('无数据')" row-key="fileUuid"
      :selection="hasModifyRight()?'multiple':'none'" separator="cell" :flat="flat" :bordered="bordered">
      <template v-slot:top="props">
        <!--功能按钮-->
        <div class="q-gutter-sm">
          <q-btn :disable="$d.selectedItems.length === 0 || workingState" @click="deleteFiles" color="red"
            icon="delete_outline" :label="$t('删除文件')" v-if="hasModifyRight()" no-caps/>
        </div>
        <!--填充所有剩余空间-->
        <q-space />
        <q-btn @click="downloadAllFilesByPack" dense flat icon="ion-md-download" :title="$t('所有附件打包下载')"
          v-if="enablePackDownload" :disable="$d.tableData.length === 0 || workingState" />
        <!--右上角全屏按钮-->
        <q-btn :icon="props.inFullscreen ? 'fullscreen_exit' : 'fullscreen'"
          :title="props.inFullscreen ? $t('退出全屏') : $t('全屏显示')" @click="props.toggleFullscreen"
          class="q-ml-sm" dense flat />
      </template>
      <template v-slot:no-data>
        <div class="full-width items-center justify-center row">
          <q-icon name="error_outline" />
          {{$t('无数据')}}
          <q-btn :disable="workingState" :loading="workingState" @click="loadListData" class="q-ml-sm" dense flat
            icon="refresh" size="sm" :title="$t('刷新')"></q-btn>
        </div>
      </template>
      <!--列插槽操作-->
      <template v-slot:body-cell-operation="props">
        <q-td :props="props">
          <a :href="fx.appCfg.apiBaseUrl + '/comm/fms/file/' + props.row.fileUuid">
            <q-btn class="q-mr-xs btn-in-row" color="primary" dense icon="eva-download" :title="$t('下载')" />
          </a>
          <a :href="fx.appCfg.apiBaseUrl + '/comm/fms/file/' + props.row.fileUuid +'?inline=true'" target="_blank">
            <q-btn class="q-mr-xs btn-in-row" color="primary" dense icon="search" :title="$t('查看')" />
          </a>
          <q-btn @click="recommentFile(props.row.fileUuid, props.row.originalFileName, props.row.comment)" class="q-mr-xs btn-in-row"
            color="primary" dense icon="edit" :title="$t('编辑')" v-if="hasModifyRight()" />
          <q-btn @click="confirmDelFile(props.row.fileUuid)" class='btn-in-row' color="red" dense icon="delete_outline"
            :title="$t('删除')" v-if="hasModifyRight()" />
        </q-td>
      </template>
    </q-table>
    <div class="q-pa-sm" v-if="hasModifyRight()">
      <q-banner class="text-white bg-red q-my-md" dense inline-actions v-if="serverErrorMessage">
        {{ serverErrorMessage }}
        <template v-slot:action>
          <q-btn @click="serverErrorMessage = ''" dense flat icon="close" size="sm" />
        </template>
      </q-banner>
      <div class="q-my-sm" v-if="hasModifyRight()">{{$t('每次上传的文件总共不要超过30MB！')}}</div>
      <div :key="item" class="row q-mt-sm" v-for="(item, index) of $d.fileListToUpload">
        <div class="col-4">
          <input @change="controlUploadBtn" :ref="el => { if (el) UploadFiles[index] = el }" type="file">
        </div>
        <div class="col-8 row q-col-gutter-sm justify-end">
          <div style="width: 80%">
            <input :maxlength="100" :placeholder="$t('备注')" :ref="el => { if (el) UploadComments[index] = el }" style="width: 100%;" type="text" class="inp">
          </div>
          <div>
            <q-btn :disable="doSubimtState" @click="removeFileForUpload(item, index)" color="red" :label="$t('移除')" no-caps/>
          </div>
        </div>
      </div>
      <div class="q-mt-sm">
        <q-btn :disable="doSubimtState" @click="addFileForUpload" class="q-mr-sm" color="primary" icon="add" no-caps
          :label="$t('增加待上传文件')" v-if="hasModifyRight()" />
        <q-btn :disable="!isUploadReady || $d.fileListToUpload.length === 0" :loading="doSubimtState" no-caps
          @click="doUploadFiles" color="primary" icon="vertical_align_top" :label="$t('上传')" v-if="hasModifyRight()" />
      </div>
    </div>
    <!--编辑文件-->
    <q-dialog persistent transition-hide="none" transition-show="none" v-model="editFileCommentDlg">
      <q-card style="max-width: 400px; width: 100%">
        <q-card-section class="q-pa-sm">
          <div class="text-h6">{{$t('编辑备注')}}</div>
        </q-card-section>
        <q-separator />
        <div class="q-pa-sm">
          <div>{{editFileName}}</div>
          <q-input :hide-bottom-space="true" dense :maxlength="100" outlined square stack-label
            v-model="$d.formEditFileComment.comment" autofocus>
          </q-input>
        </div>
        <q-separator class="separator" />
        <q-card-actions align="right">
          <q-btn @click="doRecommentFile" color="primary" :label="$t('确定')" />
          <q-btn color="primary" :label="$t('关闭')" outline unelevated v-close-popup />
        </q-card-actions>
      </q-card>
    </q-dialog>
  </div>
</template>

<script lang="ts">
export default {
  name: 'accessory'
}
</script>

<script lang="ts" setup>
import {ColumnInfo} from '../defs/comm'
import {reactive, Ref, ref} from 'vue'
import _ from 'lodash'
import { uid } from 'quasar'
import {useI18n} from 'vue-i18n'

interface PropsDef {
  // StorageClass
  storageClass: string
  // StorageId
  storageId: string|number
  // 单次上传文件的总大小限制，默认:30(M)
  maxUploadSize?: number
  // 是否启用文件打包下载功能，默认:false
  enablePackDownload?: boolean
  // 重命名文件的地址
  recommentUrl: string
  // 上传文件的地址
  uploadUrl: string
  // 删除文件的地址
  deleteUrl: string
  //菜单权限，不指定表示都有菜单权限编辑
  rightNameForEdit?: string
  //这个可以用于数据权限判定，与菜单权限的rightNameForEdit是"与"的关系
  hasEditRight?: () => boolean
  //控制q-table是否有阴影
  flat?: boolean
  //控制q-table是否有边框
  bordered?: boolean
}

const props = withDefaults(defineProps<PropsDef>(), {
  maxUploadSize: 30,
  enablePackDownload: false,
  flat: false,
  bordered: false
})

interface GetAccessoryResp {
  fileUuid: string | null,
    physicalUuid: string | null,
    storageClass: string | null,
    storageId: string | null,
    userName: string | null,
    userDispName: string | null,
    accessLevel: number,
    originalFileName: string | null,
    mimeType: string | null,
    fileSize: number,
    comment: string | null,
    internalFlag: string | null,
    createDt: Date,
    updateDt: Date
}

// 错误信息内容
let serverErrorMessage = ref('')
// 是否可上传
let isUploadReady = ref(false)
// 上传状态
let doSubimtState = ref(false)
// 控制对话框开合
let editFileCommentDlg = ref(false)
// 正在修改备注的文件名称
let editFileName = ref('')
// 编辑的文件备注ID
let editUuid = ref('')

let $d = reactive({
  tableData: [] as GetAccessoryResp[],
  // 文件分页参数
  paginationInfo: {
    page: 1,
    rowsPerPage: 0
  },
  // 多选参数
  selectedItems: [],
  // 待上传文件列表
  fileListToUpload: [] as string[],
  // 修改文件表单数据
  formEditFileComment: {
    fileUuid: '',
    comment: ''
  }
})

const {t} = useI18n()

let columnsInfo: ColumnInfo[] = [
  {
    label: t('操作'),
    name: 'operation',
    field: 'operation',
    align: 'left',
    defOrder: 1,
    defVisible: true
  },
  {
    label: t('文件名称'),
    name: 'originalFileName',
    field: 'originalFileName',
    align: 'left',
    defOrder: 2,
    defVisible: true
  },
  {
    label: t('文件大小'),
    name: 'fileSize',
    field: 'fileSize',
    align: 'left',
    defOrder: 3,
    defVisible: true,
    format: (value: any) => $f.fmt.fileSizeDisp(value as number)
  },
  {
    label: t('上传者'),
    name: 'userDispName',
    field: 'userDispName',
    align: 'left',
    defOrder: 4,
    defVisible: true,
    format: (value:any, row:GetAccessoryResp) => $f.fmt.userDisp(row.userName ?? '', row.userDispName)
  },
  {
    label: t('上传日期'),
    name: 'updateDt',
    field: 'updateDt',
    align: 'left',
    defOrder: 5,
    defVisible: true,
    format: (value: any) => $f.fmt.dtFmtFull(value as string)
  },
  {
    label: t('备注'),
    name: 'comment',
    field: 'comment',
    align: 'left',
    defOrder: 6,
    defVisible: true
  }
]

let workingState = ref(false)
// 获取附件信息
const loadListData = function () {
  workingState.value = true
  $f.axios
    .get<GetAccessoryResp[]>('/comm/fms/fileinfolist/' + String(props.storageClass) + '/' + String(props.storageId))
    .then((resp) => {
      $d.tableData = resp.data
    })
    .catch((err) => {
      $f.ui.showNotifyFailed($f.getAxiosErrMsg(err))
    })
    .finally(() => {
      workingState.value = false
    })
}
// 导出附件
const downloadAllFilesByPack = function () {
  let url = $f.misc.makeUrlWithQueryParam('/comm/fms/filepack/' + String(props.storageClass) + '/' + String(props.storageId))
  $f.nw.downloadFileWithAuth(url, '', false)
}
// 编辑文件备注
const doRecommentFile = function () {
  $d.formEditFileComment.fileUuid = editUuid.value
  $f.axios
    .post(String(props.recommentUrl), $d.formEditFileComment)
    .then(() => {
      loadListData()
      editFileCommentDlg.value = false
    })
    .catch((err) => {
      $f.ui.showNotifyFailed($f.getAxiosErrMsg(err))
    })
}
// 编辑文件ID设置
const recommentFile = function (uuid: string, fileName: string, comment: string) {
  editFileCommentDlg.value = true
  editUuid.value = uuid
  editFileName.value = fileName
  $d.formEditFileComment.comment = comment
}
// 删除多个文件
const deleteFiles = function () {
  void $f.ui.messageBox({
    caption: t('操作确认'),
    text: t('确定要删除选中附件吗?'),
    icon: 'Warning',
    buttons: 'OkCancel',
    delayClose: true
  }).then((btn) => {
    if (btn === 'ok') {
      doDeleteFiles(_.map($d.selectedItems, 'fileUuid'))
    }
  })
}

//emit定义
const emit = defineEmits<{
  (e: 'files-deleted', data: string[]): void
  (e: 'files-uploaded', data: (string | null)[]): void
}>()

// 确定删除列表附件
const doDeleteFiles = function (uuids: string[]) {
  $f.axios
    .post(String(props.deleteUrl), uuids)
    .then(() => {
      $f.ui.closeMsgBox()
      loadListData()
      emit('files-deleted', uuids)
    })
    .catch((err) => {
      $f.ui.showNotifyFailed($f.getAxiosErrMsg(err))
    })
    .finally(() => {
      $f.ui.closeMsgBox()
      $d.selectedItems = []
    })
}

// 单行删除文件按钮
const confirmDelFile = function (uuid: string) {
  void $f.ui.messageBox({
    caption: t('操作确认'),
    text: t('确定要删除选中附件吗?'),
    icon: 'Warning',
    buttons: 'OkCancel',
    delayClose: true
  }).then((btn) => {
    if (btn === 'ok') {
      doDeleteFiles([uuid])
    }
  })
}

// 文件上传输入框
let UploadFiles:Ref<HTMLInputElement[]> = ref([])
// 文件备注输入框
let UploadComments:Ref<HTMLInputElement[]> = ref([])

// 确保上传按钮是否可用
const controlUploadBtn = function () {
  let isReady = true
  if ($d.fileListToUpload.length === 0) {
    isReady = false
  } else {
    for (let i = 0; i < $d.fileListToUpload.length; i++) {
      if (!(UploadFiles.value[i]?.files![0])) {
        isReady = false
        break
      }
    }
  }
  isUploadReady.value = isReady
}

interface UploadResp {
  failedFiles: string | null
  succeededFiles: GetAccessoryResp[]
}
// 上传方法
const doUploadFiles = function () {
  // 检查文件总大小是否超过指定的尺寸
  let totalSize = 0
  for (let i = 0; i < $d.fileListToUpload.length; i++) {
    const file = UploadFiles.value[i]?.files![0]
    if (!file) {
      continue
    }
    totalSize += file.size
  }
  totalSize /= 1000 * 1000
  if (totalSize >= props.maxUploadSize) {
    serverErrorMessage.value = t('要上传的文件的总大小超过了{size}MB，请考虑分多次上传', {size: String(props.maxUploadSize)})
    return
  }

  serverErrorMessage.value = ''
  doSubimtState.value = true
  let formData = new window.FormData()
  for (let i = 0; i < $d.fileListToUpload.length; i++) {
    formData.append('Lines[' + String(i) + '].File', UploadFiles.value[i]!.files![0])
    formData.append('Lines[' + String(i) + '].Comment', UploadComments.value[i].value)
  }
  $f.axios
    .post<UploadResp>(String(props.uploadUrl) + String(props.storageId), formData)
    .then((resp) => {
      $d.fileListToUpload = []
      loadListData()
      emit('files-uploaded', _.map(resp.data.succeededFiles, 'fileUuid'))
    })
    .catch((err) => {
      $f.ui.showNotifyFailed($f.getAxiosErrMsg(err))
    })
    .finally(() => {
      doSubimtState.value = false
    })
}
// 新增一个待上传
const addFileForUpload = function () {
  let uuid = uid()
  $d.fileListToUpload.push(uuid)
  controlUploadBtn()
}
// 移除一个待上传
const removeFileForUpload = function (item: string, index: number) {
  $d.fileListToUpload.splice(index, 1)
  UploadFiles.value.splice(index, 1)
  controlUploadBtn()
}

const hasModifyRight = function(){
  return (!props.rightNameForEdit || fx.hasModifyRight(props.rightNameForEdit))
    && (!props.hasEditRight || props.hasEditRight())
}

loadListData()


defineExpose({
  loadListData
})
const fx = $f

</script>
